<!DOCTYPE html>
<html lang="en">
    

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="format-detection" content="telephone=no">
    <meta name="keywords" content="函数式编程范式, JavaScript, 一缕轻风">
    <meta name="description" content="为什么要学习函数式编程
函数式编程随着React的流行越来越收关注
Vue 3也开始拥抱函数式编程
函数式编程可以抛弃this
打包过程中可以更好的利用 tree shaking 过滤无用代码
方便测试，方便并行处理
有很多库可以帮助我们进">
    <link rel="stylesheet" type="text/css" href="/blog/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/animate.css/animate.min.css">
    
    <!-- 是否加载使用自带的 prismjs. -->
    <link rel="stylesheet" href="/blog/libs/prism/prism-tomorrow-night.css">
    <link rel="stylesheet" type="text/css" href="/blog/libs/prism/prism-line-numbers.css">
    
    
    <!-- Material Icons -->
    <link rel="stylesheet" type="text/css" href="/blog/libs/materialicons/materialicons.css">
    
    <!-- Fontawesome Icons -->
    <link rel="stylesheet" type="text/css" href="/blog/libs/fontawesome/css/all.min.css">
    <!-- aos -->
    <link rel="stylesheet" type="text/css" href="/blog/libs/aos/aos.css">
    <!-- The theme css -->
    <link rel="stylesheet" type="text/css" href="/blog/css/xxcoding.css">

    
    <!-- Your css -->
    <link rel="stylesheet" type="text/css" href="/blog/css/my.css">
    
    <!-- 
        
            
                <link rel="stylesheet" type="text/css" href="/libs/fontawesome/css/all.min.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/animate.css/animate.min.css">
            
        
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/prism/prism-tomorrow-night.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/materialicons/materialicons.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/aplayer/APlayer.min.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/tocbot/tocbot.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/libs/aplayer/Meting.min.js">
            
        
            
                <link rel="stylesheet" type="text/css" href="/css/xxcoding.css">
            
        
            
                <link rel="stylesheet" type="text/css" href="/css/my.css">
            
        
     -->
    <!-- 
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500">
    
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Marck+Script">
     -->
    

    <!-- Custom Head -->
    

    <title>函数式编程范式 | 一缕轻风</title>
    <link rel="icon" type="image/png" href="/blog/img/favicon.png">
    <script src="/blog/libs/jquery/jquery.min.js"></script>
<meta name="generator" content="Hexo 6.0.0"></head>

<body>
    <header class="navbar-fixed">
    <!-- <nav class="nav-extended pushpin"> -->
    <nav class="nav-color nav-transparent" id="nav-header" color-on-scroll="100">
        <div class="container">
            <div class="nav-wrapper">
                <a class="brand-logo waves-effect waves-light" href="/">
                    
                    <img src="/blog/img/logo.png" class="circle logo-img lazyload" data-src="/blog/img/logo.png" alt="logo">
                    
                    <span class="logo-span">一缕轻风</span>
                </a>
                <a href="#" data-target="nav-mobile" class="sidenav-trigger">
    <i class="material-icons">menu</i>
</a>
<ul class="right hide-on-med-and-down">
    
        
            <li>
                
                
                <a class="nav-item waves-effect waves-light" href="/" style="display: flex;">
                    <i class="material-icons">home</i>
                
                    <span class="nav-menu">首页</span>
                </a>
                
            </li>
        
    
        
            <li>
                
                
                <a class="nav-item waves-effect waves-light" href="/categories" style="display: flex;">
                    <i class="material-icons">chrome_reader_mode</i>
                
                    <span class="nav-menu">Categories</span>
                </a>
                
            </li>
        
    
        
            <li>
                
                
                <a class="nav-item waves-effect waves-light" href="/tags" style="display: flex;">
                    <i class="material-icons">label</i>
                
                    <span class="nav-menu">Tags</span>
                </a>
                
            </li>
        
    
        
            <li>
                
                
                <a class="nav-item waves-effect waves-light" href="/timeline" style="display: flex;">
                    <i class="material-icons">timeline</i>
                
                    <span class="nav-menu">时间线</span>
                </a>
                
            </li>
        
    
        
            <li>
                
                
                <a class="nav-item waves-effect waves-light" href="/about" style="display: flex;">
                    <i class="material-icons">account_circle</i>
                
                    <span class="nav-menu">关于</span>
                </a>
                
            </li>
        
    
    <li>
        <a class="nav-item modal-trigger waves-effect waves-light" href="#searchModal">
            <i class="material-icons">search</i>
            <!-- <i id="searchIcon" class="fas fa-search" title="Search" style="zoom: 0.6;"></i> -->
        </a>
    </li>
</ul>

            </div>
        </div>
    </nav>
</header>
<div class="sidenav" id="nav-mobile">
    <div class="user-view">
        <div class="background overlay">
            <img class="lazyload" src="/blog/img/bg/bg-1.jpg" data-src="/blog/img/bg/bg-1.jpg">
        </div>
        <img class="circle responsive-img lazyload" src="/blog/img/logo.png" data-src="/blog/img/logo.png">
        <div class="name white-text">一缕轻风</div>
        <div class="description white-text"></div>
    </div>
    <ul>
        
            
                <li>
                    
                    
                    <a class="waves-effect" href="/" style="display: flex;">
                        <i class="material-icons">home</i>
                    
                        <span>首页</span>
                    </a>
                    
                </li>
            
        
            
                <li>
                    
                    
                    <a class="waves-effect" href="/categories" style="display: flex;">
                        <i class="material-icons">chrome_reader_mode</i>
                    
                        <span>Categories</span>
                    </a>
                    
                </li>
            
        
            
                <li>
                    
                    
                    <a class="waves-effect" href="/tags" style="display: flex;">
                        <i class="material-icons">label</i>
                    
                        <span>Tags</span>
                    </a>
                    
                </li>
            
        
            
                <li>
                    
                    
                    <a class="waves-effect" href="/timeline" style="display: flex;">
                        <i class="material-icons">timeline</i>
                    
                        <span>时间线</span>
                    </a>
                    
                </li>
            
        
            
                <li>
                    
                    
                    <a class="waves-effect" href="/about" style="display: flex;">
                        <i class="material-icons">account_circle</i>
                    
                        <span>关于</span>
                    </a>
                    
                </li>
            
        
    </ul>
</div>


    <style>
    
    .post-content pre.line-numbers {
        padding: 2.2rem 1.5rem 0.5rem 3.8rem !important;
    }

    /* 行号位置 */
    .line-numbers .line-numbers-rows {
        top: 2.5rem;        /* 2.2rem + 0.3rem */
    }
    
    
    /* mac主题效果 */
    .post-content pre.line-numbers::after {
        content: '';
        position: absolute;
        display: block;
        border-radius: 50%;
        background: #ff5f56!important;
        width: 10px!important;
        height: 10px!important;
        top: 12px!important;
        left: 12px!important;
        -webkit-box-shadow: 16px 0 #ffbd2e, 32px 0 #27c93f;
        box-shadow: 16px 0 #ffbd2e, 32px 0 #27c93f;
    }
    
    
    /* 代码块语言 */
    .post-content pre.line-numbers::before {
        color: #ccc;
        font-size: .6rem;
        font-weight: 600;
        height: 25px;
        line-height: 25px;
        padding: 5px 10px 0;
        position: absolute;
        right: 0;
        text-align: right;
        top: 0;
        content: attr(data-language);
    }
    
</style>
<main>
    <!-- 文章封面 -->
    <div class="post-cover">
    <div class="cover-background">
        
        <div class="pattern repeat lazyload" data-src="/blog/img/icon-seamless.png"
            style="background-image: url('/blog/img/icon-seamless.png');">
            
        </div>
        
    </div>
    <div class="container">
        <div class="row">
            <div class="col-md-8">
                <div class="brand">
                    <h4>函数式编程范式</h4>
                </div>

            </div>
        </div>
    </div>
</div>

    <div class="container has-cover-container post-container">
        <div class="row">
            
                <div class="col s12 m12 l9" id="post-body">
                    <!-- 文章详情 -->
                    <div id="post-detail">
    <div class="card main main-raised">
        <div class="post-content">
            <h2 id="为什么要学习函数式编程"><a href="#为什么要学习函数式编程" class="headerlink" title="为什么要学习函数式编程"></a>为什么要学习函数式编程</h2><ul>
<li>函数式编程随着React的流行越来越收关注</li>
<li>Vue 3也开始拥抱函数式编程</li>
<li>函数式编程可以抛弃this</li>
<li>打包过程中可以更好的利用 tree shaking 过滤无用代码</li>
<li>方便测试，方便并行处理</li>
<li>有很多库可以帮助我们进行函数式开发：lodash、underscore、ramda</li>
</ul>
<h2 id="函数式编程的概念"><a href="#函数式编程的概念" class="headerlink" title="函数式编程的概念"></a>函数式编程的概念</h2><p>函数式编程(Functional Programming)，缩写(FP)，是编程范式之一。<br>编程范式或叫程序设计法(Programming paradigm)、编程风格、思维模式。 编程范式还有 面向过程编程、面向对象编程、响应式编程、指令式编程、声明式编程等。</p>
<p>面向对象编程的思维方式：把现实世界中的食物抽象成程序世界中的类和对象，通过封装、继承和多态来演示事物事件的联系</p>
<p>函数式编程的思维方式：把现实世界的事物和事物之间的联系抽象到程序世界（对运算过程进行抽象）</p>
<ul>
<li>程序的本质：根据输入通过某种运算获得相应的输出，程序开发过程中会涉及很多输入和输出的函数</li>
<li>函数式编程中的函数指的不是程序中的函数（方法），而是数学中的函数映射关系，例如y&#x3D;f(x)， x和y的关系</li>
<li>相同的输入始终要得到相同的输出（纯函数）</li>
<li>函数式编程用来描述数据（函数）之间的映射</li>
</ul>
<h2 id="函数是一等公民"><a href="#函数是一等公民" class="headerlink" title="函数是一等公民"></a>函数是一等公民</h2><ul>
<li>函数可以存储在变量中</li>
<li>函数作为参数</li>
<li>函数作为返回值</li>
</ul>
<h2 id="高阶函数"><a href="#高阶函数" class="headerlink" title="高阶函数"></a>高阶函数</h2><ul>
<li>可以把函数作为参数传递给另一个函数</li>
<li>可以把函数作为另一个函数的返回结果</li>
</ul>
<h3 id="函数作为参数"><a href="#函数作为参数" class="headerlink" title="函数作为参数"></a>函数作为参数</h3><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// forEach</span>
<span class="token keyword">function</span> <span class="token function">forEach</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> array<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token function">fn</span><span class="token punctuation">(</span>array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// filter</span>
<span class="token keyword">function</span> <span class="token function">filter</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> results <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> array<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
       <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span>array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
           results<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
       <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> results
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">]</span>
<span class="token function">forEach</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token function">filter</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> item <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="函数作为返回值"><a href="#函数作为返回值" class="headerlink" title="函数作为返回值"></a>函数作为返回值</h3><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 函数作为返回值</span>
<span class="token keyword">function</span> <span class="token function">makeFn</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> msg <span class="token operator">=</span> <span class="token string">'Hello Function'</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> fn <span class="token operator">=</span> <span class="token function">makeFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>应用：实现一个once函数</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">once</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> done <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>done<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            done <span class="token operator">=</span> <span class="token boolean">true</span>
            <span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> pay <span class="token operator">=</span> <span class="token function">once</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">money</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">支付了</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>money<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string"> RMB</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token comment">// 只会支付一次</span>
<span class="token function">pay</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span>
<span class="token function">pay</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span>
<span class="token function">pay</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="高阶函数的意义"><a href="#高阶函数的意义" class="headerlink" title="高阶函数的意义"></a>高阶函数的意义</h3><ul>
<li>抽象可以帮我们屏蔽细节，只需要关注我的目标</li>
<li>高阶函数是用来抽象的问题</li>
</ul>
<h3 id="常用高阶函数"><a href="#常用高阶函数" class="headerlink" title="常用高阶函数"></a>常用高阶函数</h3><ul>
<li>forEach</li>
<li>map</li>
<li>every</li>
<li>some</li>
<li>find&#x2F;findIndex</li>
<li>reduce</li>
<li>sort</li>
<li>……</li>
</ul>
<p><strong>模拟实现map</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">map</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> results <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> value <span class="token keyword">of</span> array<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
       results<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> 
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> results
<span class="token punctuation">&#125;</span>
<span class="token comment">// 测试</span>
<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token function">map</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token parameter">v</span> <span class="token operator">=></span> v <span class="token operator">**</span> <span class="token number">2</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token comment">// [ 1, 4, 9, 16 ]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>模拟实现every</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">every</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> value <span class="token keyword">of</span> array<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">break</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> result
<span class="token punctuation">&#125;</span>
<span class="token comment">// 测试</span>
<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">11</span><span class="token punctuation">,</span> <span class="token number">21</span><span class="token punctuation">,</span> <span class="token number">32</span><span class="token punctuation">,</span> <span class="token number">41</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token function">every</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token parameter">v</span> <span class="token operator">=></span> v <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token comment">// true</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>模拟实现some</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">some</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> value <span class="token keyword">of</span> array<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">break</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> result
<span class="token punctuation">&#125;</span>
<span class="token comment">// 测试</span>
<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token function">some</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token parameter">v</span> <span class="token operator">=></span> v <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token comment">// true</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span>

## 闭包

### 概念

闭包（Closure）：函数和其周围状态（词法环境）的引用捆绑在一起形成闭包。

<span class="token operator">-</span> 可以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域的成员
<span class="token operator">-</span> 闭包的本质：函数在执行的时候会放到一个执行栈上，当函数执行完毕之后会从执行栈上移除，<span class="token operator">**</span>但堆上的作用域成员因为被外部引用不能释放<span class="token operator">**</span>，因此内部函数依然可以访问外部函数的成员。
<span class="token operator">-</span> 闭包的好处是：延长了外部函数内部变量的作用范围。

<span class="token operator">**</span>示例<span class="token operator">**</span>

<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span>`javascript
<span class="token comment">// 计算n次方</span>
<span class="token keyword">function</span> <span class="token function">makePower</span><span class="token punctuation">(</span><span class="token parameter">power</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">number</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> Math<span class="token punctuation">.</span><span class="token function">pow</span><span class="token punctuation">(</span>number<span class="token punctuation">,</span> power<span class="token punctuation">)</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> power2 <span class="token operator">=</span> <span class="token function">makePower</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> power3 <span class="token operator">=</span> <span class="token function">makePower</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">power2</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">power2</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">power3</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="纯函数"><a href="#纯函数" class="headerlink" title="纯函数"></a>纯函数</h2><p>函数式编程中的“函数”指的就是纯函数，纯函数只依赖于参数，不会产生副作用。</p>
<h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><ul>
<li>纯函数：<strong>相同的输入永远会得到相同的输出</strong>，而且没有任何可观察的副作用</li>
<li>纯函数就类似数学中的函数（用来描述输入和输出之间的关系），y&#x3D;f(x)</li>
<li>函数式编程不会保留中间计算结果，所以变量是不可变的（无状态的）</li>
<li>可以把一个函数的执行结果交给另一个函数去处理</li>
</ul>
<h3 id="loadsh"><a href="#loadsh" class="headerlink" title="loadsh"></a>loadsh</h3><p>lodash 是一个纯函数的功能库，提供了对数组、数字、对象、字符串、函数等操作的一些方法</p>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> _ <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> array <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'jack'</span><span class="token punctuation">,</span> <span class="token string">'tom'</span><span class="token punctuation">,</span> <span class="token string">'lucy'</span><span class="token punctuation">,</span> <span class="token string">'kate'</span><span class="token punctuation">]</span>
<span class="token keyword">const</span> users <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token punctuation">&#123;</span> <span class="token string-property property">'user'</span><span class="token operator">:</span> <span class="token string">'barney'</span><span class="token punctuation">,</span> <span class="token string-property property">'age'</span><span class="token operator">:</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token string-property property">'active'</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#123;</span> <span class="token string-property property">'user'</span><span class="token operator">:</span> <span class="token string">'fred'</span><span class="token punctuation">,</span> <span class="token string-property property">'age'</span><span class="token operator">:</span> <span class="token number">40</span><span class="token punctuation">,</span> <span class="token string-property property">'active'</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#123;</span> <span class="token string-property property">'user'</span><span class="token operator">:</span> <span class="token string">'pebbles'</span><span class="token punctuation">,</span> <span class="token string-property property">'age'</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string-property property">'active'</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">&#125;</span>
<span class="token punctuation">]</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">first</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">last</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">toUpper</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">first</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span>array<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>item<span class="token punctuation">,</span> index<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>array<span class="token punctuation">,</span> <span class="token string">'jack'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span>users<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">user</span><span class="token operator">:</span> <span class="token string">'fred'</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>_<span class="token punctuation">.</span><span class="token function">findIndex</span><span class="token punctuation">(</span>array<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token operator">=></span> item <span class="token operator">===</span> <span class="token string">'jack'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="纯函数的好处"><a href="#纯函数的好处" class="headerlink" title="纯函数的好处"></a>纯函数的好处</h3><ul>
<li>可缓存:因为纯函数对相同输入始终有相同的结果，所以可以把纯函数的结果缓存起来</li>
<li>可测试:纯函数让测试更方便</li>
<li>并行处理: 在多线程环境下并行操作共享的内存数据很可能会出现意外情况;纯函数不需要访问共享的内存数据，所以在并行环境下可以任意运行纯函数（Web Worker）</li>
</ul>
<p><strong>模拟一个memoize函数</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">memoize</span> <span class="token punctuation">(</span><span class="token parameter">f</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
 <span class="token keyword">let</span> cache <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
 <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
     <span class="token keyword">let</span> key <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>arguments<span class="token punctuation">)</span>
     cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token function">f</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>f<span class="token punctuation">,</span> arguments<span class="token punctuation">)</span>
     <span class="token keyword">return</span> cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span>
 <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">getArea</span> <span class="token punctuation">(</span><span class="token parameter">r</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span>
    <span class="token keyword">return</span> Math<span class="token punctuation">.</span><span class="token constant">PI</span> <span class="token operator">*</span> r <span class="token operator">*</span> r
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> getAreaWithMemory <span class="token operator">=</span> <span class="token function">memoize</span><span class="token punctuation">(</span>getArea<span class="token punctuation">)</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">getAreaWithMemory</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">getAreaWithMemory</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">getAreaWithMemory</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="纯函数的副作用"><a href="#纯函数的副作用" class="headerlink" title="纯函数的副作用"></a>纯函数的副作用</h3><p>对于相同的输入永远会得到相同的输出，而且没有任何可观察的<strong>副作用</strong></p>
<p>副作用让一个函数变得不纯，纯函数根据相同的输入返回相同的输出，如果函数依赖于外部状态就无法保证输出相同，就会带来副作用。副作用一般来源：</p>
<ul>
<li>配置文件</li>
<li>数据库</li>
<li>获取用户的输入</li>
<li>……</li>
</ul>
<p>所有的外部交互都有可能带来副作用，副作用也使得方法通用性下降不适合扩展和可用性，同时副作用会给程序带来安全隐患，给程序带来不确定性，但是副作用不可能完全禁止，尽可能控制它们在可控范围发生。</p>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 不纯的</span>
<span class="token keyword">let</span> mini <span class="token operator">=</span> <span class="token number">18</span>
<span class="token keyword">function</span> <span class="token function">checkAge</span> <span class="token punctuation">(</span><span class="token parameter">age</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token keyword">return</span> age <span class="token operator">>=</span> mini
<span class="token punctuation">&#125;</span>

<span class="token comment">// 纯的（有硬编码，可用柯里化解决）</span>
<span class="token keyword">function</span> <span class="token function">checkAge</span> <span class="token punctuation">(</span><span class="token parameter">age</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> mini <span class="token operator">=</span> <span class="token number">18</span>
  <span class="token keyword">return</span> age <span class="token operator">>=</span> mini
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="柯里化（Haskell-Brooks-Curry）"><a href="#柯里化（Haskell-Brooks-Curry）" class="headerlink" title="柯里化（Haskell Brooks Curry）"></a>柯里化（Haskell Brooks Curry）</h2><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript">函数的柯里化
<span class="token keyword">function</span> <span class="token function">checkAge</span> <span class="token punctuation">(</span><span class="token parameter">min</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">age</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> age <span class="token operator">>=</span> min
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> checkAge18 <span class="token operator">=</span> <span class="token function">checkAge</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> checkAge22 <span class="token operator">=</span> <span class="token function">checkAge</span><span class="token punctuation">(</span><span class="token number">22</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">checkAge18</span><span class="token punctuation">(</span><span class="token number">21</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">checkAge22</span><span class="token punctuation">(</span><span class="token number">26</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="lodash中的柯里化函数"><a href="#lodash中的柯里化函数" class="headerlink" title="lodash中的柯里化函数"></a>lodash中的柯里化函数</h3><p>柯里化函数可以把任意多参数的函数转化为一元函数</p>
<p><strong>_.curry(func):</strong></p>
<ul>
<li>功能： 创建一个函数，该函数接收一个或多个func的参数，如果func所需要的参数都被提供则执行 func 并返回执行的结果，否则继续返回该函数并等待接收剩余的参数。</li>
<li>参数：需要柯里化的函数</li>
<li>返回值：柯里化后的函数</li>
</ul>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> _ <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span>
<span class="token keyword">function</span> <span class="token function">getSum</span> <span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> a <span class="token operator">+</span> b <span class="token operator">+</span> c
<span class="token punctuation">&#125;</span>
<span class="token keyword">const</span> curried <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">curry</span><span class="token punctuation">(</span>getSum<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">curried</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">curried</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">curried</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="柯里化实现原理"><a href="#柯里化实现原理" class="headerlink" title="柯里化实现原理"></a>柯里化实现原理</h3><p><strong>模拟实现 lodash 中的 curry 方法</strong><br> <pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">curry</span> <span class="token punctuation">(</span><span class="token parameter">func</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">curriedFn</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 判断实参个数和形参个数（func.length可以获得func的形参个数）</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>args<span class="token punctuation">.</span>length <span class="token operator">&lt;</span> func<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                <span class="token keyword">return</span> <span class="token function">curriedFn</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>arguments<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> <span class="token function">func</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></p>
<h3 id="柯里化总结"><a href="#柯里化总结" class="headerlink" title="柯里化总结"></a>柯里化总结</h3><ul>
<li>柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数</li>
<li>这是一种对函数参数的“缓存”</li>
<li>让函数变得更灵活，让函数的粒度更小</li>
<li>可以把多元函数转换成一元函数，可以组合使用函数产生强大的功能</li>
</ul>
<h2 id="函数组合（Compose）"><a href="#函数组合（Compose）" class="headerlink" title="函数组合（Compose）"></a>函数组合（Compose）</h2><p>纯函数和柯里化很容易写出洋葱代码 <code>h(g(f(x)))</code>,例如获取数组的最后一个元素再转换成大写字母，<code>_.toUpper(_.first(_.reverse(array)))</code>，函数组合可以让我们把细粒度的函数重新组合生成一个新的函数</p>
<p><strong>函数组合</strong></p>
<ul>
<li>函数组合（compose）：如果一个函数要经过多个函数处理才能得到最终值，这个时候可以把中间过程的函数合并成一个函数。</li>
<li>函数就像是数据的管道，函数组合就是把这些管道连接起来，让数据穿过多个管道形成最终结果</li>
<li><strong>函数组合默认是从右往左执行</strong></li>
</ul>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">compose</span> <span class="token punctuation">(</span><span class="token parameter">f<span class="token punctuation">,</span> g</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">function</span> <span class="token function">reverse</span> <span class="token punctuation">(</span><span class="token parameter">array</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> array<span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">function</span> <span class="token function">first</span> <span class="token punctuation">(</span><span class="token parameter">array</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> array<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span>
<span class="token comment">// 获取数组最后一个元素</span>
<span class="token keyword">const</span> last <span class="token operator">=</span> <span class="token function">compose</span><span class="token punctuation">(</span>first<span class="token punctuation">,</span> reverse<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">last</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="lodash-中的组合函数"><a href="#lodash-中的组合函数" class="headerlink" title="lodash 中的组合函数"></a>lodash 中的组合函数</h3><p>lodash 中的组合函数 <code>flow</code>和<code>flowRight</code>，可以组合多个函数:</p>
<ul>
<li><code>flow</code>：从左往右运行</li>
<li><code>flowRight</code>：从右往左运行，使用更多一些</li>
</ul>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> _ <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token function-variable function">reverse</span> <span class="token operator">=</span> <span class="token parameter">arr</span> <span class="token operator">=></span> arr<span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token function-variable function">first</span> <span class="token operator">=</span> <span class="token parameter">arr</span> <span class="token operator">=></span> arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
<span class="token keyword">const</span> <span class="token function-variable function">toUpper</span> <span class="token operator">=</span> <span class="token parameter">s</span> <span class="token operator">=></span> s<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> f <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>toUpper<span class="token punctuation">,</span> first<span class="token punctuation">,</span> reverse<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'one'</span><span class="token punctuation">,</span> <span class="token string">'two'</span><span class="token punctuation">,</span> <span class="token string">'three'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// THREE</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="组合函数原理模拟"><a href="#组合函数原理模拟" class="headerlink" title="组合函数原理模拟"></a>组合函数原理模拟</h3><p><strong>模拟实现 lodash 中的flowRight</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">reverse</span> <span class="token operator">=</span> <span class="token parameter">arr</span> <span class="token operator">=></span> arr<span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token function-variable function">first</span> <span class="token operator">=</span> <span class="token parameter">arr</span> <span class="token operator">=></span> arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
<span class="token keyword">const</span> <span class="token function-variable function">toUpper</span> <span class="token operator">=</span> <span class="token parameter">s</span> <span class="token operator">=></span> s<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// function compose (...args) &#123;</span>
<span class="token comment">//     return function (value) &#123;</span>
<span class="token comment">//         return args.reverse().reduce(function (acc, fn) &#123;</span>
<span class="token comment">//             return fn(acc)</span>
<span class="token comment">//         &#125;, value)</span>
<span class="token comment">//     &#125;</span>
<span class="token comment">// &#125;</span>
<span class="token keyword">const</span> <span class="token function-variable function">compose</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token parameter">value</span> <span class="token operator">=></span> args<span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">acc<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">fn</span><span class="token punctuation">(</span>acc<span class="token punctuation">)</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span>
<span class="token keyword">const</span> f <span class="token operator">=</span> <span class="token function">compose</span><span class="token punctuation">(</span>toUpper<span class="token punctuation">,</span> first<span class="token punctuation">,</span> reverse<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'one'</span><span class="token punctuation">,</span> <span class="token string">'two'</span><span class="token punctuation">,</span> <span class="token string">'three'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="lodash中的fp模块"><a href="#lodash中的fp模块" class="headerlink" title="lodash中的fp模块"></a>lodash中的fp模块</h3><ul>
<li>lodash的fp模块提供了实用的对<strong>函数式编程友好</strong>的方法</li>
<li>lodash中的方法：数据优先，函数滞后</li>
<li>lodash&#x2F;fp 模块中的方法：函数优先，数据滞后</li>
</ul>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> fp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash/fp'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> f<span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> fp<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span>toLower<span class="token punctuation">)</span><span class="token punctuation">,</span> fp<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token string">'NEVER SAY DIE'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>

<h2 id="Pointfree"><a href="#Pointfree" class="headerlink" title="Pointfree"></a>Pointfree</h2><p>Pointfree：我们可以把数据处理的过程定义成与数据无关的合成运算，不需要用到代表数据的那个参数，只要把简单的运算步骤合成到一起，在使用这种模式之前我们需要定义一些辅助的基本运算函数。</p>
<ul>
<li>不需要指明处理的数据</li>
<li><strong>只需要合成运算过程</strong></li>
<li>需要定义一些辅助的基本运算函数</li>
</ul>
<p><strong>示例</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 非 Pointfree</span>
<span class="token keyword">function</span> <span class="token function">f</span> <span class="token punctuation">(</span><span class="token parameter">word</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> word<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\s+</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'_'</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token string">'Hello     World'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="函子"><a href="#函子" class="headerlink" title="函子"></a>函子</h2><p><strong>函子：</strong>是一个特殊的容器，通过一个普通的对象来实现，该对象具有map方法，map方法可以运行一个函数对值进行处理（并行关系）</p>
<h3 id="Functor-函子"><a href="#Functor-函子" class="headerlink" title="Functor 函子"></a>Functor 函子</h3><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// class Container &#123;</span>
<span class="token comment">//     constructor (value) &#123;</span>
<span class="token comment">//         this._value = value</span>
<span class="token comment">//     &#125;</span>
<span class="token comment">//     map (fn) &#123;</span>
<span class="token comment">//         return new Container(fn(this._value))</span>
<span class="token comment">//     &#125;</span>
<span class="token comment">// &#125;</span>
<span class="token comment">// let r = new Container(4).map(x => x + 2).map(x => x * x)</span>
<span class="token comment">// console.log(r)</span>
<span class="token keyword">class</span> <span class="token class-name">Container</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 添加 of 方法用于创建 Container 实例</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Container</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> value
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> Container<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> Container<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x <span class="token operator">*</span> x<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="函子总结"><a href="#函子总结" class="headerlink" title="函子总结"></a>函子总结</h3><ul>
<li>函数式编程的运算不直接操作值，而是由函子完成</li>
<li>函子就是实现了 map 契约的对象</li>
<li>我们可以把函子想象成一个盒子，这个盒子里封装了一个值</li>
<li>想要处理盒子的值，我们需要给盒子的 map 方法传递一个处理值的函数（纯函数），由这个函数来对值进行处理</li>
<li>最终 map 方法返回一个包含新值的盒子（函子）</li>
</ul>
<h3 id="MayBe-函子"><a href="#MayBe-函子" class="headerlink" title="MayBe 函子"></a>MayBe 函子</h3><ul>
<li>问题：多次调用map时，不确定哪次出现null</li>
</ul>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">MayBe</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">MayBe</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> value
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">isNothing</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span> MayBe<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token operator">:</span> MayBe<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">isNothing</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">===</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">===</span> <span class="token keyword">undefined</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token comment">// let r = MayBe.of('hello world').map(x => x.toUpperCase())</span>
<span class="token comment">// console.log(r)</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> MayBe<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="Either-函子"><a href="#Either-函子" class="headerlink" title="Either 函子"></a>Either 函子</h3><ul>
<li>Either：两者中的任何一个，类似于if…else…的处理</li>
<li>异常会让函数变得不纯，Either 函子 可以用来做异常处</li>
</ul>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">Left</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Left</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> value
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">class</span> <span class="token class-name">Right</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Right</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> value
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> Right<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">function</span> <span class="token function">parseJSON</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> Right<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> Left<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>error<span class="token punctuation">.</span>message<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> r1 <span class="token operator">=</span> <span class="token function">parseJSON</span><span class="token punctuation">(</span><span class="token string">'&#123; name: zs &#125;'</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r1<span class="token punctuation">)</span>
<span class="token keyword">let</span> r2 <span class="token operator">=</span> <span class="token function">parseJSON</span><span class="token punctuation">(</span><span class="token string">'&#123; "name": "zs" &#125;'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r2<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="IO-函子"><a href="#IO-函子" class="headerlink" title="IO 函子"></a>IO 函子</h3><ul>
<li>IO 函子中的 _value 是一个函数，这里是把函数作为值来处理</li>
<li>IO 函子可以吧不纯的动作存储到_value 中，延迟执行这个不纯的操作（惰性执行），包装后当前的操作是纯的操作</li>
<li>把不纯的操作交给调用者来处理</li>
</ul>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">IO</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> value
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> fn
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 把当前的 value 和传入的 fn 组合成一个新的函数</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>fn<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token constant">IO</span><span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span>process<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">p</span> <span class="token operator">=></span> p<span class="token punctuation">.</span>execPath<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">.</span><span class="token function">_value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>IO 函子的问题</strong></p>
<p>调用嵌套函子中的函数时非常不方便。</p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> fp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash/fp'</span><span class="token punctuation">)</span>
<span class="token keyword">class</span> <span class="token class-name">IO</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> value
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> fn
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token comment">// 把当前的 value 和传入的 fn 组合成一个新的函数</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>fn<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> <span class="token function-variable function">readFile</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">filename</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> <span class="token function-variable function">print</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">x</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span>
        <span class="token keyword">return</span> x
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> cat <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>print<span class="token punctuation">,</span> readFile<span class="token punctuation">)</span>
<span class="token comment">// IO(IO(x))</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token function">cat</span><span class="token punctuation">(</span><span class="token string">'package.json'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">_value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">_value</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="folktale"><a href="#folktale" class="headerlink" title="folktale"></a>folktale</h3><p><strong>Folktale：</strong>一个标准的函数式编程库，和loadsh、ramda不同的是，他没有提供很多功能函数，只提供了一些函数式处理的操作、例如：compose、curry等，一些函子Task、Either、MayBe等</p>
<p><strong>folktale 中的 curry、compose 函数</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> curry<span class="token punctuation">,</span> compose <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'folktale/core/lambda'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">&#123;</span>toUpper<span class="token punctuation">,</span> first <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> f1 <span class="token operator">=</span> <span class="token function">curry</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> x <span class="token operator">+</span> y
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f1</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f1</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> f2 <span class="token operator">=</span> <span class="token function">compose</span><span class="token punctuation">(</span>toUpper<span class="token punctuation">,</span> first<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f2</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'one'</span><span class="token punctuation">,</span> <span class="token string">'two'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>folktale 中的Task函子：处理异步任务</strong></p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">&#123;</span> task <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'folktale/concurrency/task'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">&#123;</span> split<span class="token punctuation">,</span> find <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash/fp'</span><span class="token punctuation">)</span>
<span class="token keyword">function</span> <span class="token function">readFile</span> <span class="token punctuation">(</span><span class="token parameter">filename</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token function">task</span><span class="token punctuation">(</span><span class="token parameter">resolver</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
                resolver<span class="token punctuation">.</span><span class="token function">reject</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
            <span class="token punctuation">&#125;</span>
            resolver<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'package.json'</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'version'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
        <span class="token function-variable function">onRejected</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token function-variable function">onResolved</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="Pointed-函子"><a href="#Pointed-函子" class="headerlink" title="Pointed 函子"></a>Pointed 函子</h3><ul>
<li>Pointed 函子是实现了 of 静态方法的函子</li>
<li>of 方法是为了避免使用 new 来创建对象，更深层的含义是of方法是用来把值放到上下文 Context （把值放到容器中，使用map 来处理值）</li>
</ul>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">Container</span> <span class="token punctuation">&#123;</span>
	<span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
		<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Container</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
	<span class="token punctuation">&#125;</span>
	……
<span class="token punctuation">&#125;</span>

	Container<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x <span class="token operator">+</span> <span class="token number">5</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="Monad-函子"><a href="#Monad-函子" class="headerlink" title="Monad 函子"></a>Monad 函子</h3><p>Monad 函子 是可以变扁的 Pointed函子，IO(IO(x))，一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个Monad</p>
<pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> fp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash/fp'</span><span class="token punctuation">)</span>
<span class="token keyword">class</span> <span class="token class-name">IO</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">static</span> <span class="token keyword">of</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">return</span> value
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_value <span class="token operator">=</span> fn
    <span class="token punctuation">&#125;</span>
    <span class="token function">map</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">flowRight</span><span class="token punctuation">(</span>fn<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_value<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">join</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">_value</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    <span class="token function">flatMap</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> <span class="token function-variable function">readFile</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">filename</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> <span class="token function-variable function">print</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">x</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">IO</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span>
        <span class="token keyword">return</span> x
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> r <span class="token operator">=</span> <span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'package.json'</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span>toUpper<span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span>print<span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
        </div>
        <div class="post-comment">
            

    <style>
    .v[data-class=v] .vinput {
        padding: unset;
    }
</style>
<div id="vcomments"></div>

<script src="/blog/libs/valine/Valine.min.js"></script>

<script>
    new Valine({
        el: '#vcomments',
        appId: 'Mia2Oc0sFRP8CLKWIpkzlKH7-gzGzoHsz',
        appKey: 'UzWr1AJYRlfkoKpaNY9l2dIW',
        notify: 'false' === 'true',
        verify: 'false' === 'true',
        visitor: 'true' === 'true',
        avatar: 'monsterid',
        pageSize: '10',
        lang: '',
        // lang: 'en',
        placeholder: '发一条友善的评论',
        emojiCDN: 'https://i0.hdslb.com/bfs/emote/',
        emojiMaps: {
            "doge": "3087d273a78ccaff4bb1e9972e2ba2a7583c9f11.png",
            "微笑": "685612eadc33f6bc233776c6241813385844f182.png",
            "OK": "4683fd9ffc925fa6423110979d7dcac5eda297f4.png",
            "星星眼": "63c9d1a31c0da745b61cdb35e0ecb28635675db2.png",
            "妙啊": "b4cb77159d58614a9b787b91b1cd22a81f383535.png",
            "辣眼睛": "35d62c496d1e4ea9e091243fa812866f5fecc101.png",
            "吃瓜": "4191ce3c44c2b3df8fd97c33f85d3ab15f4f3c84.png",
            "滑稽": "d15121545a99ac46774f1f4465b895fe2d1411c3.png",
            "呲牙": "b5a5898491944a4268360f2e7a84623149672eb6.png",
            "打call": "431432c43da3ee5aab5b0e4f8931953e649e9975.png",
            "歪嘴": "4384050fbab0586259acdd170b510fe262f08a17.png",
            "调皮": "8290b7308325e3179d2154327c85640af1528617.png",
            "嗑瓜子": "28a91da1685d90124cfeead74622e1ebb417c0eb.png",
            "笑哭": "c3043ba94babf824dea03ce500d0e73763bf4f40.png",
            "脱单doge": "bf7e00ecab02171f8461ee8cf439c73db9797748.png",
            "给心心": "1597302b98827463f5b75c7cac1f29ea6ce572c4.png",
            "嘟嘟": "abd7404537d8162720ccbba9e0a8cdf75547e07a.png",
            "喜欢": "8a10a4d73a89f665feff3d46ca56e83dc68f9eb8.png",
            "酸了": "92b1c8cbceea3ae0e8e32253ea414783e8ba7806.png",
            "哦呼": "362bded07ea5434886271d23fa25f5d85d8af06c.png",
            "嫌弃": "de4c0783aaa60ec03de0a2b90858927bfad7154b.png",
            "大哭": "2caafee2e5db4db72104650d87810cc2c123fc86.png",
            "害羞": "9d2ec4e1fbd6cb1b4d12d2bbbdd124ccb83ddfda.png",
            "疑惑": "b7840db4b1f9f4726b7cb23c0972720c1698d661.png",
            "喜极而泣": "485a7e0c01c2d70707daae53bee4a9e2e31ef1ed.png",
            "奸笑": "bb84906573472f0a84cebad1e9000eb6164a6f5a.png",
            "笑": "81edf17314cea3b48674312b4364df44d5c01f17.png",
            "偷笑": "6c49d226e76c42cd8002abc47b3112bc5a92f66a.png",
            "惊讶": "f8e9a59cad52ae1a19622805696a35f0a0d853f3.png",
            "捂脸": "6921bb43f0c634870b92f4a8ad41dada94a5296d.png",
            "阴险": "ba8d5f8e7d136d59aab52c40fd3b8a43419eb03c.png",
            "囧": "12e41d357a9807cc80ef1e1ed258127fcc791424.png",
            "呆": "33ad6000d9f9f168a0976bc60937786f239e5d8c.png",
            "抠鼻": "cb89184c97e3f6d50acfd7961c313ce50360d70f.png",
            "大笑": "ca94ad1c7e6dac895eb5b33b7836b634c614d1c0.png",
            "惊喜": "0afecaf3a3499479af946f29749e1a6c285b6f65.png",
            "无语": "44667b7d9349957e903b1b62cb91fb9b13720f04.png",
            "点赞": "1a67265993913f4c35d15a6028a30724e83e7d35.png",
            "鼓掌": "895d1fc616b4b6c830cf96012880818c0e1de00d.png",
            "尴尬": "cb321684ed5ce6eacdc2699092ab8fe7679e4fda.png",
            "灵魂出窍": "43d3db7d97343c01b47e22cfabeca84b4251f35a.png",
            "委屈": "d2f26cbdd6c96960320af03f5514c5b524990840.png",
            "傲娇": "010540d0f61220a0db4922e4a679a1d8eca94f4e.png",
            "疼": "905fd9a99ec316e353b9bd4ecd49a5f0a301eabf.png",
            "冷": "cb0ebbd0668640f07ebfc0e03f7a18a8cd00b4ed.png",
            "生病": "0f25ce04ae1d7baf98650986454c634f6612cb76.png",
            "吓": "9c10c5ebc7bef27ec641b8a1877674e0c65fea5d.png",
            "吐": "06946bfe71ac48a6078a0b662181bb5cad09decc.png",
            "捂眼": "c5c6d6982e1e53e478daae554b239f2b227b172b.png",
            "嘘声": "e64af664d20716e090f10411496998095f62f844.png",
            "思考": "cfa9b7e89e4bfe04bbcd34ccb1b0df37f4fa905c.png",
            "再见": "fc510306bae26c9aec7e287cdf201ded27b065b9.png",
            "翻白眼": "eba54707c7168925b18f6f8b1f48d532fe08c2b1.png",
            "哈欠": "888d877729cbec444ddbd1cf4c9af155a7a06086.png",
            "奋斗": "bb2060c15dba7d3fd731c35079d1617f1afe3376.png",
            "墨镜": "3a03aebfc06339d86a68c2d893303b46f4b85771.png",
            "难过": "a651db36701610aa70a781fa98c07c9789b11543.png",
            "撇嘴": "531863568e5668c5ac181d395508a0eeb1f0cda4.png",
            "抓狂": "4c87afff88c22439c45b79e9d2035d21d5622eba.png",
            "生气": "3195714219c4b582a4fb02033dd1519913d0246d.png",
            "口罩": "3ad2f66b151496d2a5fb0a8ea75f32265d778dd3.png",
            "牛年": "9275275ff1f2659310648221107d20bc4970f106.png",
            "福到了": "5de5373d354c373cf1617b6b836f3a8d53c5a655.png",
            "鸡腿": "c7860392815d345fa69c4f00ef18d67dccfbd574.png",
            "月饼": "89b19c5730e08d6f12fadf6996de5bc2e52f81fe.png",
            "雪花": "a41813c4edf8782047e172c884ebd4507ce5e449.png",
            "视频卫星": "dce6fc7d6dfeafff01241924db60f8251cca5307.png",
            "干杯": "8da12d5f55a2c7e9778dcc05b40571979fe208e6.png",
            "爱心": "ed04066ea7124106d17ffcaf75600700e5442f5c.png",
            "锦鲤": "643d6c19c8164ffd89e3e9cdf093cf5d773d979c.png",
            "胜利": "b49fa9f4b1e7c3477918153b82c60b114d87347c.png",
            "加油": "c7aaeacb21e107292d3bb053e5abde4a4459ed30.png",
            "抱拳": "89516218158dbea18ab78e8873060bf95d33bbbe.png",
            "响指": "1b5c53cf14336903e1d2ae3527ca380a1256a077.png",
            "保佑": "fafe8d3de0dc139ebe995491d2dac458a865fb30.png",
            "支持": "3c210366a5585706c09d4c686a9d942b39feeb50.png",
            "拥抱": "41780a4254750cdaaccb20735730a36044e98ef3.png",
            "跪了": "f2b3aee7e521de7799d4e3aa379b01be032698ac.png",
            "怪我咯": "07cc6077f7f7d75b8d2c722dd9d9828a9fb9e46d.png",
            "黑洞": "e90ec4c799010f25391179118ccd9f66b3b279ba.png",
            "老鼠": "8e6fb491eb1bb0d5862e7ec8ccf9a3da12b6c155.png",
            "凛冬-生气": "d90bd2fbc13a3cb8d313f6d675f20caf109f60a7.png",
            "W-哈哈": "83d527303c8f62f494e6971c48836487e7d87b1b.png",
            "霜叶-疑问": "ada3aea8594e724511c1daad15fb3b23900d8e24.png",
            "煌-震撼": "7bb39ac289bc97fe52af047020a9bf324ecdebe1.png",
            "哭泣": "a61abafb8c39defc323b045f30072198007b1c89.png",
            "狗子": "6a997106af5bf490f22c80a7acf3be813ee755fc.png",
            "羞羞": "f4f9171e4d8c3f30827a8b96ea1ce1beb825ad50.png",
            "亲亲": "2f72bae7b834d499f259c833f7011d5ed8748fd1.png",
            "耍帅": "d7a38b08d1f1cc35b19c35041f29ffcc48808e87.png",
            "气愤": "069b029d17a086ab475fd331697a649e234850bb.png",
            "高兴": "416570a8aca7be12fb2c36e4b846906653f6d294.png",
        }
    })
</script>



        </div>

    </div>
</div>

                </div>
                <div class="col l3" id="toc-body">
                    <!-- 文章目录 -->
                    <link rel="stylesheet" href="/blog/libs/tocbot/tocbot.css">
<style>
    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget #toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    #toc-content .toc-list {
        padding-left: 10px;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ul li, #toc-content ol li {
        padding-left: 10px;
        line-height: 1.8rem;
        font-size: 1rem;
        color: #444;
    }

    #toc-content .is-active-link {
        color: #E91E63;
    }

    #toc-content .is-active-link::before {
        background-color: transparent;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
    }

    .toc-widget {
        box-shadow: 0 16px 24px 2px rgb(0 0 0 / 14%), 0 6px 30px 5px rgb(0 0 0 / 12%), 0 8px 10px -5px rgb(0 0 0 / 20%);
    }

</style>
<div id="post-toc">
    <div class="toc-widget card">
        <div id="toc-title">
            <i class="far fa-list-alt"></i>&nbsp;&nbsp;目录
        </div>
        <div id="toc-content"></div>
    </div>
</div>
<script src="/blog/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function() {
        tocbot.init({
            // Where to render the table of contents.
            tocSelector: '#toc-content',
            // Where to grab the headings to build the table of contents.
            contentSelector: '.post-content',
            // Which headings to grab inside of the contentSelector element.
            headingSelector: 'h1, h2, h3, h4',
            // For headings inside relative or absolute positioned containers within content.
            hasInnerContainers: false,
            // Smooth scrolling enabled.
            scrollSmooth: true,
            // Smooth scroll duration.
            scrollSmoothDuration: 420,
            headingsOffset: $('#nav-header').height() + 10,
            scrollSmoothOffset: -($('#nav-header').height() + 10),
            collapseDepth: 4,
            // orderedList can be set to false to generate unordered lists (ul)
            // instead of ordered lists (ol)
            orderedList: false,
        });

        // 动态设置文章目录的宽度， 防止滚动和窗口变动时变形
        // width()不包含padding, innerWidth()包含padding
        $('.toc-widget').width($('#toc-body').width());

        let tocHeight = parseInt($(window).height() * 0.5 - 64);
        let $tocWidget = $('.toc-widget');
        let $tocTitle = $('#toc-title');
        let $tocContent = $('#toc-content');
        if ($(window).scrollTop() > tocHeight) {
            $tocWidget.addClass('toc-fixed');
        } else {
            $tocWidget.removeClass('toc-fixed');
        }
        $tocWidget.css('max-height', $(window).height() * 0.6);
        if ($tocContent.height() > ($tocWidget.height() - $tocTitle.height())) {
            $tocWidget.css('overflow-y', 'auto');
        }
        // if ($tocWidget.height() > $(window).height() * 0.6) {
        //     $tocWidget.css('max-height', $(window).height() * 0.6);
        // }
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
            if ($tocContent.height() > ($tocWidget.height() - $tocTitle.height())) {
                $tocWidget.css('overflow-y', 'auto');
            } else {
                $tocWidget.css('overflow-y', 'unset');
            }
            $('.toc-widget').width($('#toc-body').width());
        });
        $(window).on('resize', function(){
            $tocWidget.css('max-height', $(window).height() * 0.6);
            if ($tocContent.height() > ($tocWidget.height() - $tocTitle.height())) {
                $tocWidget.css('overflow-y', 'auto');
            } else {
                $tocWidget.css('overflow-y', 'unset');
            }
            $('.toc-widget').width($('#toc-body').width());
        });
    });
</script>

                </div>
            
        </div>
    </div>
</main>

    <footer class="page-footer footer-color">
    
        
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.css">


<style type="text/css">
    .aplayer.aplayer-fixed {
        z-index: 999;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    

    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #b7daff;
    }
</style>

<div class="">
    <div class="row">
        <meting-js
            class="col l8 offset-l2 m10 offset-m1 s12"
            server="netease"
            type="playlist"
            id="743950282"
            fixed='true'
            autoplay='false'
            theme='#b7daff'
            loop='all'
            order='random'
            preload='auto'
            volume='0.7'
            list-folded='true'>
        </meting-js>
    </div>
</div>


<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.js"></script>


<script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script>


    
    <div class="container">
        <div class="row center">
            <div class="col l12 m12 s12">
                <div id="framework-info">
                    Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
                    &nbsp;
                </div>
                <div id="siteinfo">
                    <!-- <span>站点总字数：</span> -->
                    
                </div>
                
                <div id="sitetime">载入运行时间...</div>
                <script>
                    function siteTime() {
                        var seconds = 1000;
                        var minutes = seconds * 60;
                        var hours = minutes * 60;
                        var days = hours * 24;
                        var years = days * 365;
                        var today = new Date();
                        var startYear = "2021";
                        var startMonth = "2";
                        var startDate = "19";
                        var startHour = "0";
                        var startMinute = "0";
                        var startSecond = "0";
                        var todayYear = today.getFullYear();
                        var todayMonth = today.getMonth() + 1;
                        var todayDate = today.getDate();
                        var todayHour = today.getHours();
                        var todayMinute = today.getMinutes();
                        var todaySecond = today.getSeconds();
                        var t1 = Date.UTC(startYear, startMonth, startDate, startHour, startMinute, startSecond);
                        var t2 = Date.UTC(todayYear, todayMonth, todayDate, todayHour, todayMinute, todaySecond);
                        var diff = t2 - t1;
                        var diffYears = Math.floor(diff / years);
                        var diffDays = Math.floor((diff / days) - diffYears * 365);
                        var diffHours = Math.floor((diff - (diffYears * 365 + diffDays) * days) / hours);
                        var diffMinutes = Math.floor((diff - (diffYears * 365 + diffDays) * days - diffHours * hours) /
                            minutes);
                        var diffSeconds = Math.floor((diff - (diffYears * 365 + diffDays) * days - diffHours * hours -
                            diffMinutes * minutes) / seconds);
                        if (startYear == todayYear) {
                            document.getElementById("year").innerHTML = todayYear;
                            document.getElementById("sitetime").innerHTML = "本站已持续运行 " + "<span class='white-text'>" + diffDays + "</span>" + " 天 "
                            + "<span class='white-text'>" + diffHours + "</span>" + " 小时 "
                            + "<span class='white-text'>" + diffMinutes + "</span>" + " 分钟 "
                            + "<span class='white-text'>" + diffSeconds + "</span>" + " 秒";
                        } else {
                            document.getElementById("year").innerHTML = startYear + " - " + todayYear;
                            document.getElementById("sitetime").innerHTML = "本站已持续运行 " + "<span class='white-text'>" + diffYears + "</span>" + " 年 "
                            + "<span class='white-text'>" + diffDays + "</span>" + " 天 "
                            + "<span class='white-text'>" + diffHours + "</span>" + " 小时 "
                            + "<span class='white-text'>" + diffMinutes + "</span>" + " 分钟 "
                            + "<span class='white-text'>" + diffSeconds + "</span>" + " 秒";
                        }
                    }
                    setInterval(siteTime, 1000);
                </script>
                
                
                
            </div>
        </div>
    </div>
    <div class="footer-copyright">
        <div class="container center">
            Copyright&nbsp;&copy;
            
                <span id="year">2021 - 2022</span>
            
            ,&nbsp;
            made with <span style="color: red;">❤️</span>&nbsp;&nbsp;by
            <a href="/blog/about" target="_blank">ice-matcha</a>
            for a better web.
        </div>
    </div>
</footer>


    
    <!-- 回到顶部按钮 -->
<div id="back-top" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>

    

    <script src="/blog/libs/materialize/materialize.min.js"></script>
<script src="/blog/libs/lazyload/lazyload.min.js"></script>
<script src="/blog/libs/aos/aos.js"></script>
<script src="/blog/js/xxcoding.js"></script>


<script src="https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/autoload.js"></script>


</body>
</html>
